import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from sklearn.decomposition import PCA
from sklearn.preprocessing import StandardScaler
import seaborn as sns

# 设置随机种子保证结果可重现
np.random.seed(42)


def generate_wine_data(n_samples=500):
    """
    生成葡萄酒品质数据集（500个样本）
    基于真实的葡萄酒化学特性
    """
    # 创建三个品质等级：普通40%，优质35%，特级25%
    n_ordinary = int(n_samples * 0.4)
    n_premium = int(n_samples * 0.35)
    n_exceptional = n_samples - n_ordinary - n_premium

    print(f"Sample distribution: Ordinary {n_ordinary}, Premium {n_premium}, Exceptional {n_exceptional}")

    # 类别1: 普通葡萄酒
    alcohol1 = np.random.normal(11.0, 0.8, n_ordinary)  # 酒精度
    acidity1 = np.random.normal(6.5, 0.6, n_ordinary)  # 酸度
    sugar1 = np.random.normal(4.0, 0.8, n_ordinary)  # 残糖量
    tannin1 = np.random.normal(1.5, 0.4, n_ordinary)  # 单宁含量

    # 类别2: 优质葡萄酒
    alcohol2 = np.random.normal(12.8, 0.6, n_premium)
    acidity2 = np.random.normal(5.8, 0.4, n_premium)
    sugar2 = np.random.normal(2.5, 0.5, n_premium)
    tannin2 = np.random.normal(2.5, 0.3, n_premium)

    # 类别3: 特级葡萄酒
    alcohol3 = np.random.normal(14.2, 0.4, n_exceptional)
    acidity3 = np.random.normal(5.2, 0.3, n_exceptional)
    sugar3 = np.random.normal(1.5, 0.3, n_exceptional)
    tannin3 = np.random.normal(3.2, 0.2, n_exceptional)

    # 组合数据
    features = np.vstack([
        np.column_stack([alcohol1, acidity1, sugar1, tannin1]),
        np.column_stack([alcohol2, acidity2, sugar2, tannin2]),
        np.column_stack([alcohol3, acidity3, sugar3, tannin3])
    ])

    # 创建标签
    labels = np.array([0] * n_ordinary + [1] * n_premium + [2] * n_exceptional)

    # 创建DataFrame
    wine_df = pd.DataFrame(features,
                           columns=['alcohol', 'acidity', 'residual_sugar', 'tannin'])
    wine_df['quality'] = labels
    wine_df['quality_label'] = wine_df['quality'].map({0: 'Ordinary', 1: 'Premium', 2: 'Exceptional'})

    return wine_df


# 生成500个葡萄酒样本
print("Generating 500 sample wine dataset...")
wine_data = generate_wine_data(500)

print("\nDataset Overview:")
print(wine_data.head())
print(f"\nDataset shape: {wine_data.shape}")
print("\nSamples per class:")
print(wine_data['quality_label'].value_counts())

# 数据标准化
features = wine_data[['alcohol', 'acidity', 'residual_sugar', 'tannin']]
scaler = StandardScaler()
features_scaled = scaler.fit_transform(features)

# PCA分析
pca = PCA()
principal_components = pca.fit_transform(features_scaled)

# 创建PCA结果的DataFrame
pca_df = pd.DataFrame(data=principal_components,
                      columns=[f'PC{i + 1}' for i in range(principal_components.shape[1])])
pca_df['quality'] = wine_data['quality']
pca_df['quality_label'] = wine_data['quality_label']

# 方差分析
explained_variance = pca.explained_variance_ratio_
cumulative_variance = np.cumsum(explained_variance)

print(f"\nPCA Results:")
print("Explained variance ratio:")
for i, (var, cum_var) in enumerate(zip(explained_variance, cumulative_variance)):
    print(f"PC{i + 1}: {var:.3f} ({var:.1%}) | Cumulative: {cum_var:.3f} ({cum_var:.1%})")

# 找到保留85%方差所需的主成分数量
n_components_85 = np.argmax(cumulative_variance >= 0.85) + 1
print(f"\nComponents needed for 85% variance: {n_components_85}")

# 可视化结果
plt.figure(figsize=(15, 10))

# 图1: 方差解释图（碎石图）
plt.subplot(2, 2, 1)
plt.bar(range(1, len(explained_variance) + 1), explained_variance, alpha=0.7, label='Individual')
plt.plot(range(1, len(cumulative_variance) + 1), cumulative_variance, 'ro-', label='Cumulative')
plt.axhline(y=0.85, color='r', linestyle='--', alpha=0.5, label='85% threshold')
plt.axvline(x=n_components_85, color='g', linestyle='--', alpha=0.5, label=f'{n_components_85} components')
plt.xlabel('Principal Components')
plt.ylabel('Explained Variance Ratio')
plt.title('PCA Scree Plot - Variance Explanation')
plt.legend()
plt.grid(True, alpha=0.3)

# 图2: 原始特征空间
plt.subplot(2, 2, 2)
colors = {'Ordinary': 'red', 'Premium': 'blue', 'Exceptional': 'green'}
for quality, color in colors.items():
    mask = wine_data['quality_label'] == quality
    plt.scatter(wine_data.loc[mask, 'alcohol'],
                wine_data.loc[mask, 'acidity'],
                c=color, label=quality, alpha=0.6, s=30)
plt.xlabel('Alcohol (%)')
plt.ylabel('Acidity (pH)')
plt.title('Original Features: Alcohol vs Acidity (500 samples)')
plt.legend()
plt.grid(True, alpha=0.3)

# 图3: PCA降维结果
plt.subplot(2, 2, 3)
for quality, color in colors.items():
    mask = pca_df['quality_label'] == quality
    plt.scatter(pca_df.loc[mask, 'PC1'],
                pca_df.loc[mask, 'PC2'],
                c=color, label=quality, alpha=0.6, s=30)
plt.xlabel(f'PC1 ({explained_variance[0]:.1%} variance)')
plt.ylabel(f'PC2 ({explained_variance[1]:.1%} variance)')
plt.title('PCA Results - First Two Components')
plt.legend()
plt.grid(True, alpha=0.3)

# 图4: 特征在主成分空间中的贡献
plt.subplot(2, 2, 4)
feature_names = ['alcohol', 'acidity', 'sugar', 'tannin']
pca_loadings = pca.components_.T * np.sqrt(pca.explained_variance_)

for i, feature in enumerate(feature_names):
    plt.arrow(0, 0, pca_loadings[i, 0], pca_loadings[i, 1],
              color='r', alpha=0.7, head_width=0.05)
    plt.text(pca_loadings[i, 0] * 1.15, pca_loadings[i, 1] * 1.15,
             feature, color='r', ha='center', va='center', fontsize=9)

plt.xlabel('PC1')
plt.ylabel('PC2')
plt.title('Feature Directions in PCA Space')
plt.grid(True, alpha=0.3)
plt.axis('equal')

plt.tight_layout()
plt.show()

# 详细分析
print("\n" + "=" * 50)
print("DETAILED PCA ANALYSIS")
print("=" * 50)

# 特征对主成分的贡献度
print("\nFeature Loadings (Contributions to PCs):")
loadings_df = pd.DataFrame(pca.components_.T,
                           columns=[f'PC{i + 1}' for i in range(pca.components_.shape[0])],
                           index=feature_names)
print(loadings_df.round(3))

# 样本在主成分空间中的坐标
print(f"\nFirst 5 samples in PCA space:")
for i in range(5):
    sample_info = f"Sample {i}: "
    for j in range(min(3, n_components_85)):
        sample_info += f"PC{j + 1}={pca_df.iloc[i][f'PC{j + 1}']:.2f} "
    sample_info += f"({wine_data.iloc[i]['quality_label']})"
    print(sample_info)

# 降维效果总结
print(f"\nDimensionality Reduction Summary:")
print(f"- Original dimensions: 4")
print(f"- Reduced dimensions: {n_components_85}")
print(f"- Dimension reduction: {(1 - n_components_85 / 4) * 100:.1f}%")
print(f"- Information preserved: {cumulative_variance[n_components_85 - 1]:.1%}")

# 相关性分析
print(f"\nFeature Correlation Matrix:")
correlation_matrix = wine_data[['alcohol', 'acidity', 'residual_sugar', 'tannin', 'quality']].corr()
print(correlation_matrix.round(3))

# 保存数据集
wine_data.to_csv('wine_quality_500_samples.csv', index=False)
print(f"\n数据已保存'")

# 额外分析：各类别在主成分空间中的分离情况
print(f"\nClass Distribution in PCA Space:")
for quality in ['Ordinary', 'Premium', 'Exceptional']:
    mask = pca_df['quality_label'] == quality
    pc1_mean = pca_df.loc[mask, 'PC1'].mean()
    pc2_mean = pca_df.loc[mask, 'PC2'].mean()
    print(f"{quality}: PC1 mean = {pc1_mean:.3f}, PC2 mean = {pc2_mean:.3f}")

# 主成分解释
print(f"\nPrincipal Components Interpretation:")
print("PC1 mainly represents: Comprehensive indicator of alcohol and tannin content (overall wine quality)")
print("PC2 mainly represents: Balance indicator of acidity and sugar")
print("PC3 mainly represents: Combination of other minor features")

# PCA在葡萄酒数据分析中的应用价值
print(f"\nPCA Application Value in Wine Data Analysis:")
print("1. Dimensionality reduction visualization: Reduce 4D data to 2D for visualization")
print("2. Feature extraction: Identify key chemical indicators affecting wine quality")
print("3. Quality classification: Provide features for subsequent wine quality classification models")
print("4. Anomaly detection: Identify abnormal wine samples that do not conform to regular patterns")